<template>
  <div style="width:100%;height:100%">
    <div ref="search" style="position:absolute;right:10px;top:10px;z-index: 100;padding:5px;border-radius: 5px;width:200px;border:1px solid #AAAAAA;opacity: 0.5;">
      <div ref="label" style="font-size: 14px;color:#FFFFFF;">储位位置：6排货架1层12列1格</div>
      <div style="font-size: 15px;color:#FFFFFF;"><span>料箱编码：</span><span ref="lxCode">A3293434922</span></div>
      <div>
        <div style="color:#FFFFFF;">物品列表:</div>
        <div ref="wlCode1" style="color:#FFFFFF;width:90%;border:1px solid #1c32b5;border-radius: 5px;background-color: #1c32b5;margin: 5px auto;">G34i932452</div>
        <div ref="wlCode2" style="color:#FFFFFF;width:90%;border:1px solid #1c32b5;border-radius: 5px;background-color: #1c32b5;margin: 5px auto">G34i932452</div>
        <div ref="wlCode3" style="color:#FFFFFF;width:90%;border:1px solid #1c32b5;border-radius: 5px;background-color: #1c32b5;margin: 5px auto">G34i932452</div>
        <div ref="wlCode4" style="color:#FFFFFF;width:90%;border:1px solid #1c32b5;border-radius: 5px;background-color: #1c32b5;margin: 5px auto">G34i932452</div>
      </div>
    </div>
    <div id="container"></div>
  </div>
</template>

<script>
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
import Stats from 'three/addons/libs/stats.module.js';
import TWEEN from '@tweenjs/tween.js';
import * as THREE from 'three'
export default {
  name: "agv-demo",
  data() {
    return{
      container:null,//容器
      secne: null,
      camera: '',  //相机对象
      controls: null,//控制器对象
      renderer: null,  //渲染器对象
      mesh: null,  //网格模型对象Mesh
      stats:undefined,
      shelfList:[],
      storageUnitList:[],
      rackRowCount:4,//货架排数
      rackColCount:3,//货架列数
      layerNum:5,//货架层数
      columnNum:5,//每层货格数

      floor:{ //设置地板的宽高厚
        floorLength:600,floorWidth:550,floorDepth:1
      },
      box:{//料箱大小
        boxLength:10,boxWidth:10,boxDepth:10
      },
      plane:{planeLength:58,planeWidth: 35,planeHeight:2},//  层板的长,宽，高
      holder:{holderLength:2, holderHeight:15,holderWidth:2}, //架腿长,宽，高
      wallHeight:20,//墙壁的高度
      indistanceX: 60,//货架距离墙边x轴距离
      indistanceY: 150,//货架距离墙边Y轴距离
      cameraPointList:[],
      agvList:[],
      selectedBox:[],
      lastBoxName: '',
      lastLayer:{
        name:'',
        z:''
      },
    }
  },
  methods:{
    //初始化场景
    initScene(){
      this.secne = new THREE.Scene();
      this.stats = new Stats();
      document.body.appendChild(this.stats.domElement);
    },
    //初始化相机
    initCamera(){
      this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
      this.camera.position.set(-300, 600, 600);
      this.camera.up.set(0, 0, 1);   // <=== spin // around Z-axis
    },
    //初始化灯光
    initLight(){
      let directionalLight = new THREE.DirectionalLight(0xffffff, 1); //模拟远处类似太阳的光源
      directionalLight.color.setHSL(0.1, 1, 0.95);
      directionalLight.position.set(0, 200, 500).normalize();
      this.secne.add(directionalLight);
      let ambient = new THREE.AmbientLight(0xffffff, 1); //AmbientLight,影响整个场景的光源
      ambient.position.set(0, 0, 500);
      this.secne.add(ambient);
    },
    //添加天空
    addSkybox() {
      let loader = new THREE.CubeTextureLoader();// 创建一个CubeTextureLoader
      let texture = loader.load([ // 加载天空盒子的六个面的图像
        '/static/images/sky/posx.jpg', // 底部面的图像
        'static/images/sky/negx.jpg', // 右侧面的图像
        '/static/images/sky/negz.jpg', // 后侧面的图像
        '/static/images/sky/posz.jpg', // 前侧面的图像
        '/static/images/sky/posy.jpg', // 左侧面的图像
        '/static/images/sky/negy.jpg', // 顶部面的图像
      ]);
      // 将天空盒子应用到场景的背景中
      this.secne.background = texture;
      // 创建一个立方体并添加到场景中
      let skybox = new THREE.Mesh(new THREE.BoxGeometry( 2500, 2500, 2500 ));
      skybox.position.set(0,0,0)
      skybox.position.z += 700;
      this.secne.add(skybox);
    },
    //初始化地板
    initFloor(){
      let floorGeometry = new THREE.BoxGeometry( this.floor.floorLength,this.floor.floorWidth,this.floor.floorDepth);
      let cubeMaterial = new THREE.MeshPhysicalMaterial({color:'#CCCCCC'});
      let floor = new THREE.Mesh( floorGeometry, cubeMaterial );
      floor.name = '地板';
      floor.position.set(this.floor.floorLength/2,this.floor.floorWidth/2,0)
      this.secne.add(floor)
    },
    //初始化墙壁
    createCubeWall() {
      let materialTie = [];
      materialTie.push(new THREE.MeshPhongMaterial({color: 0xafc0ca}));  //前  0xafc0ca :灰色
      materialTie.push(new THREE.MeshPhongMaterial({color: 0x9cb2d1}));  //后  0x9cb2d1：淡紫
      materialTie.push(new THREE.MeshPhongMaterial({color: 0xd6e4ec}));  //上  0xd6e4ec： 偏白色
      materialTie.push(new THREE.MeshPhongMaterial({color: 0xd6e4ec}));  //下
      materialTie.push(new THREE.MeshPhongMaterial({color: 0xafc0ca}));  //左   0xafc0ca :灰色
      materialTie.push(new THREE.MeshPhongMaterial({color: 0xafc0ca}));  //右

      let wallList = []
      let wall1 = {width:this.floor.floorLength, height:3, depth:this.wallHeight, angle:0, matArrayB:materialTie, x:this.floor.floorLength/2, y:0, z:this.wallHeight/2, name:"墙面"};
      let wall2 = {width:this.floor.floorLength, height:3, depth:this.wallHeight, angle:1, matArrayB:materialTie, x:this.floor.floorLength/2, y:this.floor.floorWidth, z:this.wallHeight/2, name:"墙面"};
      let wall3 = {width:this.floor.floorWidth, height:3, depth:this.wallHeight, angle:1.5, matArrayB:materialTie, x:0, y:(this.floor.floorWidth/2), z:this.wallHeight/2, name:"墙面"};
      let wall4 = {width:this.floor.floorWidth, height:3, depth:this.wallHeight, angle:1.5, matArrayB:materialTie, x:this.floor.floorLength, y:(this.floor.floorWidth/2), z:this.wallHeight/2, name:"墙面"};
      wallList.push(wall1);wallList.push(wall2);wallList.push(wall3);wallList.push(wall4);
      for(let i=0;i<wallList.length;i++){
        let cubeGeometry = new THREE.BoxGeometry(wallList[i].width, wallList[i].height, wallList[i].depth);
        let cube = new THREE.Mesh(cubeGeometry, wallList[i].matArrayB);
        cube.position.x = wallList[i].x;
        cube.position.y = wallList[i].y;
        cube.position.z = wallList[i].z;
        cube.rotation.z += wallList[i].angle * Math.PI; //-逆时针旋转,+顺时针
        cube.name = wallList[i].name;
        this.secne.add(cube);
      }
    },
    //初始化货架
    initShelf(){
      for (let i = 0; i < this.rackRowCount; i++) { //循环四次产生四排
        this.indistanceX = this.indistanceX + 55;
        for (let j = 0; j < this.rackColCount; j++) { //循环三次产生三列
          let shelfName = '货架' + (j + 1) + "上"
          this.shelfList.push({
            shelfName: (i + 1) + "排_" + shelfName,
            planeWidth: this.plane.planeWidth,
            planeHeight: this.plane.planeHeight,
            planeLength: this.plane.planeLength,
            holderLength: this.holder.holderLength,
            holderHeight: this.holder.holderHeight,
            holderWidth: this.holder.holderWidth,
            positionX: this.indistanceX,
            positionY: this.indistanceY + (j * this.plane.planeLength),
            positionZ: this.holder.holderHeight + 2,
            layerNum: this.layerNum,
            columnNum: this.columnNum
          });
        }
      }
      for(let i = 0;i < this.shelfList.length; i++){
        for(let j = 0; j < this.shelfList[i].layerNum; j++){//循环每列货架的的层数
          this.addShelf(
              this.shelfList[i].positionX,
              this.shelfList[i].positionY,
              this.shelfList[i].positionZ*(j+1),
              this.shelfList[i].planeWidth,
              this.shelfList[i].planeLength,
              this.shelfList[i].planeHeight,
              this.shelfList[i].holderLength,
              this.shelfList[i].holderWidth,
              this.shelfList[i].holderHeight,
              this.shelfList[i].shelfName+"_"+(j+1)+"层",
              this.shelfList[i].columnNum);
        }
      }
    },
    //新增货架
    addShelf(x,y,z,plane_x,plane_y,plane_z,holder_x,holder_y,holder_z,name,num){
      let RackMat2 = new THREE.MeshPhongMaterial({
        color: 0xffffff, // 设置颜色
        shininess: 20 // 设置高光大小，范围为0到128，默认值为30
      });
      let plane = new THREE.BoxGeometry( plane_x, plane_y/num,plane_z);
      let gz = [];
      for(let i = 0; i < num; i++){//循环每层的个数
        gz.push( y + plane_y/num/2 + (plane_y/num)*i );
        let obj = new THREE.Mesh( plane, RackMat2 );
        obj.position.set(x, gz[i], z) ;
        obj.name = name
        this.secne.add(obj);
      }
      let holder = new THREE.BoxGeometry( holder_x, holder_y, holder_z );
      let obj2 = new THREE.Mesh( holder, RackMat2, 0 );
      let obj3 = new THREE.Mesh( holder, RackMat2, 0 );
      let obj4 = new THREE.Mesh( holder, RackMat2, 0 );
      let obj5 = new THREE.Mesh( holder, RackMat2, 0 );
      obj2.position.set(x-plane_x/2+holder_x/2,y+holder_y/2,z-holder_z/2-plane_z/2,);
      obj3.position.set(x+plane_x/2-holder_x/2,y+holder_y/2, z-holder_z/2-plane_z/2, );
      obj4.position.set(x-plane_x/2+holder_x/2,y+plane_y-holder_y/2,z-holder_z/2-plane_z/2 );
      obj5.position.set(x+plane_x/2-holder_x/2,y+plane_y-holder_y/2, z-holder_z/2-plane_z/2 );
      this.secne.add(obj2);this.secne.add(obj3);this.secne.add(obj4);this.secne.add(obj5);
    },
    //初始化料箱
    initCube(){
      for(let q=0; q<this.shelfList.length;q++){
        for(let i=0;i<this.layerNum;i++){
          for(let j=0;j<this.columnNum;j++){
            let shorageName = this.shelfList[q].shelfName + "_" + (i + 1) + "层_" + (j + 1) + "列"
            let x = this.shelfList[q].positionX;
            let y = this.shelfList[q].positionY + 6 + j * (this.plane.planeWidth / 3)
            let z = this.shelfList[q].positionZ + 4 + i * (this.holder.holderHeight + this.plane.planeHeight)
            this.addCube(x - 8, y, z, "box " + "_" + shorageName + "_1")
            this.addCube(x + 8, y, z, "box " + "_" + shorageName + "_2")
          }
        }
      }
    },
    //新增料箱
    addCube(x,y,z,name){
      let cubeMaterial = new THREE.MeshPhysicalMaterial({color:'#1c32b5',metalness: 0.5,transparent: false,});
      let geometry = new THREE.BoxGeometry(15,10,10)
      let mesh = new THREE.Mesh(geometry, cubeMaterial);
      mesh.position.set(x, y, z+1);
      mesh.name = name
      this.secne.add(mesh)
    },
    //初始化相机的飞入效果
    flyCamera(){
      const curve = new THREE.EllipseCurve(0, 0, 800, 400);
      this.cameraPointList = curve.getPoints(1000); // 分段值，数值越大，曲线越圆滑
      let tween = new TWEEN.Tween(this.camera.position).to({x:700,y:500,z:400}, 8000).start();
      tween.onUpdate(() => {
        // 在每一帧更新时执行的操作
        this.camera.lookAt(300,175,0);
      });
    },
    //选中后弹出
    alertLabel(event){
      let mouse = new THREE.Vector2();
      let x, y;
      if ( event.changedTouches ) {
        x = event.changedTouches[ 0 ].pageX;
        y = event.changedTouches[ 0 ].pageY;
      } else {
        x = event.clientX;
        y = event.clientY;
      }
      mouse.x = ( x / window.innerWidth ) * 2 - 1;
      mouse.y = - ( y / window.innerHeight ) * 2 + 1;
      let raycaster = new THREE.Raycaster();
      raycaster.setFromCamera( mouse, this.camera );
      let intersects = raycaster.intersectObjects( [ this.secne ], true );
      if(intersects.length>0 && intersects[0].object !== null){
        if(intersects[0].object.name.substring(0,3) === 'box'){
          this.focusBox(x,y,intersects[0].object);
        }else if(intersects[0].object.name.substr(-1) === '层'){
          this.focusPlane(intersects[0].object);
        }
      }
    },
    //选中料箱时触发
    focusBox(x,y,selectObject){
      if (this.lastBoxName !== '') {
        for (let i = 0; i < this.secne.children.length; i++) {
          if (this.secne.children[i].name === this.lastBoxName) {
            this.secne.children[i].material.color = new THREE.Color('#1c32b5');// 取消选中后的box
            this.secne.children[i].position.z -= 6
          }
        }
      }
      selectObject.material.color = new THREE.Color('#ec611e');//选中box颜色
      selectObject.position.z += 6
      if (this.$refs.label !== null) {
        this.$refs.label.style.display = "block"
        this.$refs.label.style.left = x + "px"
        this.$refs.label.style.top = y + "px"
        this.$refs.label.innerText = selectObject.name
        this.$refs.lxCode.innerText = "A"+ Math.round((Math.random()*89999999) + 10000000)
        this.$refs.wlCode1.innerText = "G"+ Math.round((Math.random()*89999999) + 10000000)
        this.$refs.wlCode2.innerText = "G"+ Math.round((Math.random()*89999999) + 10000000)
        this.$refs.wlCode3.innerText = "G"+ Math.round((Math.random()*89999999) + 10000000)
        this.$refs.wlCode4.innerText = "G"+ Math.round((Math.random()*89999999) + 10000000)
      }
      this.lastBoxName = selectObject.name
    },
    //选中每层时触发
    focusPlane(selectObject){
      if(this.lastLayer.name !== ''){
        for(let i=0;i<this.secne.children.length;i++){
          if(this.lastBoxName !== '' && this.secne.children[i].name === this.lastBoxName){
            this.secne.children[i].material.color = new THREE.Color('#1c32b5');//取消box颜色
            this.secne.children[i].position.z -=6
            this.lastBoxName = ''
          }
          if(this.secne.children[i].name.includes(this.lastLayer.name) && this.secne.children[i].name.length>this.lastLayer.name.length){
            this.secne.children[i].material.color = new THREE.Color('#1c32b5');//选中box颜色
            this.secne.children[i].position.z = this.lastLayer.z+6
          }
        }
      }
      for(let i=0;i<this.secne.children.length;i++){
        if(this.lastBoxName !== '' && this.secne.children[i].name === this.lastBoxName){
          this.secne.children[i].material.color = new THREE.Color('#1c32b5');//取消选中box颜色
          this.secne.children[i].position.z -=6
          this.lastBoxName = ''
        }
        if(this.secne.children[i].name.includes(selectObject.name) && this.secne.children[i].name.length>selectObject.name.length){
          this.lastLayer.name = selectObject.name
          this.lastLayer.z = selectObject.position.z
          this.secne.children[i].material.color = new THREE.Color('#1c32b5');//选中层颜色
          this.secne.children[i].position.z = this.layerNum * (this.holder.holderHeight+5)+30
        }
      }
    },
    //初始化渲染器
    initRenderer(){
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.container = document.getElementById("container")
      this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.renderer.setClearColor('#CCCCCC', 1.0);
      this.container.appendChild(this.renderer.domElement);
    },
    // 创建OrbitControls控制器
    initControl(){
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.5;
      // 视角最小距离
      this.controls.minDistance = 100;
      // 视角最远距离
      this.controls.maxDistance = 1000;
      // 最大角度
      this.controls.maxPolarAngle = Math.PI / 2.2;
      this.controls.target = new THREE.Vector3(300,175,);
      this.camera.position.set(800,600,600);
    },
    //动画渲染
    initAnimate() {
      requestAnimationFrame(this.initAnimate);
      TWEEN.update();
      this.stats.update();
      this.renderer.render(this.secne, this.camera);
    },
  },
  mounted() {
    this.initScene();
    this.initCamera();
    this.initLight();
    this.addSkybox();
    this.initFloor();
    this.createCubeWall();
    this.flyCamera();
    this.initShelf();
    this.initCube();
    this.initRenderer();
    this.initControl();
    this.initAnimate();
    window.addEventListener( 'click', this.alertLabel);
  }
}
</script>

<style scoped>
#container{
  position: absolute;
  width:100%;
  height:100%;
}

</style>
